package com.bungarus.codec;

import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.MessageLite;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpHeaderValues;
import org.apache.log4j.Logger;

import java.util.List;

/**
 * Created by tang on 2019/1/8.
 */
public class UnwrapHttpResp2ProtobufDecoder extends MessageToMessageDecoder<FullHttpResponse> {
    Logger logger = Logger.getLogger(UnwrapHttpResp2ProtobufDecoder.class);

    private static final boolean HAS_PARSER;
    static {
        boolean hasParser = false;
        try {
            MessageLite.class.getDeclaredMethod("getParserForType");
            hasParser = true;
        }
        catch (Exception e) {
        }
        HAS_PARSER = hasParser;
    }

    private final MessageLite prototype;

    public UnwrapHttpResp2ProtobufDecoder(MessageLite prototype) {
        this.prototype = prototype;
    }

    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, FullHttpResponse response, List<Object> out) throws InvalidProtocolBufferException {
        String svrName = response.headers().get(HttpHeaderNames.SERVER);
        String contentType = response.headers().get(HttpHeaderNames.CONTENT_TYPE);
        if(svrName.equalsIgnoreCase("BUNGARUS/1.0.0") &&
                contentType.equalsIgnoreCase(HttpHeaderValues.BYTES.toString())) {
            ByteBuf msg = response.content();

            final byte[] array;
            final int offset;
            final int length = msg.readableBytes();

            if (msg.hasArray()) {
                array = msg.array();
                offset = msg.arrayOffset() + msg.readerIndex();
            }
            else {
                array = ByteBufUtil.getBytes(msg, msg.readerIndex(), length, false);
                offset = 0;
            }

            if (HAS_PARSER) {
                out.add(prototype.getParserForType().parseFrom(array, offset, length));
            }
            else {
                out.add(prototype.newBuilderForType().mergeFrom(array, offset, length).build());
            }
        }
    }
}
